package com.cal.utms.model.dealing;

import java.math.BigDecimal;
import java.text.DateFormat;
import java.text.DecimalFormat;
import java.text.NumberFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
import java.util.Locale;

import com.cal.utms.dao.dealing.DealDao;
import com.cal.utms.dao.maintenance.DealTypeDao;
import com.cal.utms.dao.maintenance.IssuerDaoImpl;
import com.cal.utms.dao.maintenance.MasterDataDaoImpl;
import com.cal.utms.dao.maintenance.NewFundDao;
import com.cal.utms.dto.dealing.FdDealDto;
import com.cal.utms.entity.Deal;
import com.cal.utms.entity.Dealer;
import com.cal.utms.entity.DelevaryMethod;
import com.cal.utms.entity.Fund;
import com.cal.utms.entity.Issuer;
import com.cal.utms.entity.SettlementMethod;
import com.cal.utms.util.Sequence;
import com.cal.utms.valuation.FixedDepositeCalculator;

public class FdDealModel {

	private IssuerDaoImpl issuerDaoImpl = new IssuerDaoImpl();

	public Deal creatFdDeal(FdDealDto fdDealDto) {
		Deal deal = new Deal();
		deal.setCreatedDate(new Date());
		deal.setDealType(new DealTypeDao().getDealTypeByCode("FD"));
		deal.setCreatedUser(fdDealDto.getUser());
		deal.setStatus("Initial");

		Sequence seq = new Sequence();
		String dealCode = "FD" + seq.getNextValue("DealSequence");
		deal.setDealCode(dealCode);
		return mapDtoToDeal(fdDealDto, deal);
	}

	public Deal updateFdDeal(Deal deal, FdDealDto fdDealDto) {
		deal.setModifiedDate(new Date());
		deal.setModifiedUser(fdDealDto.getUser());
		return mapDtoToDeal(fdDealDto, deal);
	}

	private Deal mapDtoToDeal(FdDealDto fdDealDto, Deal deal) {
		DateFormat df = new SimpleDateFormat("dd/MM/yyyy", Locale.ENGLISH);
		NumberFormat nf = NumberFormat.getInstance();
		Date date = null;
		Number number;

		if (fdDealDto.getFund() != 0) {
			NewFundDao nfd = new NewFundDao();
			Fund fund = nfd.getById(fdDealDto.getFund());
			if (fund != null) {
				deal.setFund(fund);
			} else {
				fdDealDto.setSuccess(false);
				fdDealDto.setStatus("Invalid Fund!");
				return deal;
			}
		} else {
			fdDealDto.setSuccess(false);
			fdDealDto.setStatus("Empty Fund!");
			return deal;
		}
		if (fdDealDto.getIssuer() != 0) {
			IssuerDaoImpl issuerDao = new IssuerDaoImpl();
			Issuer issuer = issuerDao.getById(fdDealDto.getIssuer());
			if (issuer != null) {
				boolean allowedIssuer = false;
				List<Issuer> issuers = issuerDaoImpl.getIssuerByFundId(deal.getFund().getId());// malsha
				for (Issuer issr : issuers) {
					if (issr.getId() == issuer.getId()) {
						allowedIssuer = true;
						break;
					}
				}
				if (allowedIssuer) {
					deal.setIssuer(issuer);
				} else {
					fdDealDto.setSuccess(false);
					fdDealDto.setStatus("Issuer Not allowed!");
					return deal;
				}
			} else {
				fdDealDto.setSuccess(false);
				fdDealDto.setStatus("Invalid Issuer!");
				return deal;
			}
		} else {
			fdDealDto.setSuccess(false);
			fdDealDto.setStatus("Empty Issuer!");
			return deal;
		}
		MasterDataDaoImpl masterDataDaoImpl = new MasterDataDaoImpl();
		if (fdDealDto.getSettlementCode() != 0) {
			SettlementMethod method = masterDataDaoImpl.getSettlementById(fdDealDto.getSettlementCode());
			if (method != null)
				deal.setSettlementMethod(method);
			else {
				fdDealDto.setSuccess(false);
				fdDealDto.setStatus("Invalid Settlement Methode!");
				return deal;
			}
		}
		if (fdDealDto.getDelevarymethode() != 0) {
			DelevaryMethod delevaryMethod = masterDataDaoImpl.getDelevaryMethodById(fdDealDto.getDelevarymethode());
			if (delevaryMethod != null)
				deal.setDelevarymethode(delevaryMethod);
			else {
				fdDealDto.setSuccess(false);
				fdDealDto.setStatus("Invalid Delevary Methode!");
				return deal;
			}
		}

		if (fdDealDto.getDealerCode() != 0) {
			Dealer dealer = masterDataDaoImpl.getdealerByid(fdDealDto.getDealerCode());
			if (dealer != null)
				deal.setDealerCode(dealer);
			else {
				fdDealDto.setSuccess(false);
				fdDealDto.setStatus("Invalid Dealer!");
				return deal;
			}
		}

		if (fdDealDto.getValueDate() != null) {
			try {
				System.out.println("valDt:" + fdDealDto.getValueDate());
				date = df.parse(fdDealDto.getValueDate());
				System.out.println(date);
				deal.setValueDate(date);
			} catch (ParseException pe) {
				fdDealDto.setSuccess(false);
				fdDealDto.setStatus("Value Date Parse Error!");
				return deal;
			}
		} else {
			fdDealDto.setSuccess(false);
			fdDealDto.setStatus("Empty Value Date!");
			return deal;
		}
		if (fdDealDto.getMaturityDate() != null) {
			try {
				System.out.println("matDt:" + fdDealDto.getMaturityDate());
				date = df.parse(fdDealDto.getMaturityDate());
				deal.setMaturityDate(date);
			} catch (ParseException pe) {
				fdDealDto.setSuccess(false);
				fdDealDto.setStatus("Maturity Date Parse Error!");
				return deal;
			}
		} else {
			fdDealDto.setSuccess(false);
			fdDealDto.setStatus("Empty Value Date!");
			return deal;
		}
		if (fdDealDto.getPrincipleValue() != null) {
			try {
				number = nf.parse(fdDealDto.getPrincipleValue());
				deal.setDealValue(new BigDecimal(number.doubleValue()));
			} catch (ParseException e) {
				fdDealDto.setSuccess(false);
				fdDealDto.setStatus("Principle Value Parse Error!");
				return deal;
			}
		} else {
			fdDealDto.setSuccess(false);
			fdDealDto.setStatus("Empty Principle Value!");
			return deal;
		}

		if (fdDealDto.getPrincipleValue() != null) {
			try {
				number = nf.parse(fdDealDto.getPrincipleValue());
				deal.setMaturityValue(new BigDecimal(number.doubleValue()));
			} catch (ParseException e) {
				fdDealDto.setSuccess(false);
				fdDealDto.setStatus("Maturity Value Parse Error!");
				return deal;
			}
		} else {
			fdDealDto.setSuccess(false);
			fdDealDto.setStatus("Empty Maturity Value!");
			return deal;
		}

		String rate = fdDealDto.getActualRate().replaceAll("%", "");
		deal.setActualRate(new BigDecimal(rate));
		if (fdDealDto.getIcp() < 0) {
			fdDealDto.setSuccess(false);
			fdDealDto.setStatus("Invalid ICP");
			return deal;
		} else {
			deal.setIcp(fdDealDto.getIcp());
		}

		deal.setWithholdingTax(fdDealDto.getWithholdingTaxType());
		if (!fdDealDto.getWithholdingTaxType().equals("No")) {
			if (fdDealDto.getWithholdingTaxRate() != null) {
				String withRate = fdDealDto.getWithholdingTaxRate().replace("%", "");
				deal.setWithholdingTaxRate(new BigDecimal(withRate));
			} else {
				fdDealDto.setSuccess(false);
				fdDealDto.setStatus("Invalid Withholding Tax Rate");
				return deal;
			}
			deal.setWithholdingCertificate("NotReceived");
		} else {
			deal.setWithholdingCertificate("No");
		}
		deal.setDayBasis("Act / 365");

		if (fdDealDto.getParams() != null && !fdDealDto.getParams().trim().equals("")) {
			deal.setRolloverShortmaturity(fdDealDto.getParams());
		}
		return deal;
	}

	public FdDealDto mapFdToDto(Deal deal) {
		NumberFormat nf = new DecimalFormat("###,###.00");
		DateFormat df = new SimpleDateFormat("dd/MM/yyyy");
		FdDealDto fdDealDto = new FdDealDto();

		fdDealDto.setId(deal.getId());
		fdDealDto.setDealCode(deal.getDealCode());
		fdDealDto.setFund(deal.getFund().getId());
		fdDealDto.setIssuer(deal.getIssuer().getId());
		fdDealDto.setValueDate(df.format(deal.getValueDate()));
		fdDealDto.setMaturityDate(df.format(deal.getMaturityDate()));
		fdDealDto.setPrincipleValue(nf.format(deal.getDealValue().doubleValue()));
		fdDealDto.setActualRate(nf.format(deal.getActualRate().doubleValue()) + "%");
		fdDealDto.setIcp(deal.getIcp());

		if (deal.getWithholdingTax() != null) {
			fdDealDto.setWithholdingTaxType(deal.getWithholdingTax());
			if (!deal.getWithholdingTax().equals("No")) {
				if (deal.getWithholdingTaxRate() != null) {
					fdDealDto.setWithholdingTaxRate(nf.format(deal.getWithholdingTaxRate().doubleValue()) + "%");
				}
			}
		}
		if (deal.getMaturityValue() != null) {
			fdDealDto.setMaturityValue(nf.format(deal.getMaturityValue().doubleValue()));
		}
		if (deal.getSettlementMethod() != null)
			fdDealDto.setSettlementCode(deal.getSettlementMethod().getId());
		if (deal.getDelevarymethode() != null)
			fdDealDto.setDelevarymethode(deal.getDelevarymethode().getId());
		if (deal.getDealerCode() != null)
			fdDealDto.setDealerCode(deal.getDealerCode().getId());

		fdDealDto.setStatus(deal.getStatus());
		return fdDealDto;
	}

	public Deal confFdDeal(FdDealDto fdDealDto) {
		DealDao dealDao = new DealDao();
		Deal deal = dealDao.getByCode(fdDealDto.getDealCode());
		deal.setStatus("Confirmed");
		deal.setConfirmedUser(fdDealDto.getUser());
		deal.setConfirmedDate(new Date());
		return mapDtoToDeal(fdDealDto, deal);
	}

	public FdDealDto valuate(FdDealDto fdDealDto) {

		DateFormat df = new SimpleDateFormat("MM/dd/yyyy", Locale.ENGLISH);
		NumberFormat nf = NumberFormat.getInstance();
		Date valueDate = null;
		Date maturityDate = null;
		Number principleValue = null;

		String withRate = "0";
		if (fdDealDto.getWithholdingTaxRate() != null) {
			withRate = fdDealDto.getWithholdingTaxRate().replace("%", "");
		} else {
			withRate = "0.00";
		}

		if (fdDealDto.getValueDate() == null) {
			fdDealDto.setStatus("Empty Value Date");
			fdDealDto.setSuccess(true);
			return fdDealDto;
		} else {
			try {
				System.out.println("valDt:" + fdDealDto.getValueDate());
				valueDate = df.parse(fdDealDto.getValueDate());
				System.out.println(valueDate);
			} catch (ParseException pe) {
				fdDealDto.setSuccess(false);
				fdDealDto.setStatus("Value Date Parse Error!");
				return fdDealDto;
			}
		}
		if (fdDealDto.getMaturityDate() == null) {
			fdDealDto.setStatus("Empty Maturity Date");
			fdDealDto.setSuccess(true);
			return fdDealDto;
		} else {
			try {
				System.out.println("matDt:" + fdDealDto.getMaturityDate());
				maturityDate = df.parse(fdDealDto.getMaturityDate());
				System.out.println(maturityDate);
			} catch (ParseException pe) {
				fdDealDto.setSuccess(false);
				fdDealDto.setStatus("Maturity Date Parse Error!");
				return fdDealDto;
			}
		}
		if (fdDealDto.getWithholdingTaxType() == null) {
			fdDealDto.setStatus("Empty Withholding Tax Type");
			fdDealDto.setSuccess(true);
			return fdDealDto;
		} else if (fdDealDto.getWithholdingTaxType().equals("Maturity") || fdDealDto.getWithholdingTaxType().equals("Upfront")) {
			if (Double.parseDouble(withRate) < 0) {
				fdDealDto.setSuccess(false);
				fdDealDto.setStatus("Invalid Withholding Tax Rate");
				return fdDealDto;
			}
		} else if (!fdDealDto.getWithholdingTaxType().equals("No")) {
			fdDealDto.setStatus("Invalid Withholding Tax Type");
			fdDealDto.setSuccess(true);
			return fdDealDto;
		}

		if (fdDealDto.getPrincipleValue() == null) {
			fdDealDto.setSuccess(false);
			fdDealDto.setStatus("Empty Principle Value!");
			return fdDealDto;
		} else {
			try {
				principleValue = nf.parse(fdDealDto.getPrincipleValue());
			} catch (ParseException e) {
				fdDealDto.setSuccess(false);
				fdDealDto.setStatus("Principle Value Parse Error!");
				return fdDealDto;
			}
		}

		if (fdDealDto.getIcp() < 0) {
			fdDealDto.setSuccess(false);
			fdDealDto.setStatus("Invalid ICP");
			return fdDealDto;
		}
		FixedDepositeCalculator fixedDepo = new FixedDepositeCalculator();
		String rate = fdDealDto.getActualRate().replace("%", "");

		fixedDepo.valuateAllParameters(principleValue.doubleValue(), Double.parseDouble(rate), "Act / 365", valueDate, maturityDate, fdDealDto.getWithholdingTaxType(),
				Double.parseDouble(withRate), fdDealDto.getIcp());
		fdDealDto.setMaturityValue(nf.format(fixedDepo.getMaturityValue()));
		fdDealDto.setWithholdingTax(nf.format(fixedDepo.getWithholdingTax()));
		fdDealDto.setRate(nf.format(fixedDepo.getEffectiveRate()));

		return fdDealDto;
	}
}
